/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.pa165.languageschoolservice.serviceImpl;

import com.pa165.languageschoolpersistence.DAO.LectureDAO;
import com.pa165.languageschoolpersistence.DAO.StudentDAO;
import com.pa165.languageschoolpersistence.Exceptions.ServiceFailureException;
import com.pa165.languageschoolpersistence.entities.Lecture;
import com.pa165.languageschoolpersistence.entities.Student;
import com.pa165.languageschoolservice.DTO.LectureDTO;
import com.pa165.languageschoolservice.DTO.StudentDTO;
import com.pa165.languageschoolservice.service.StudentService;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author Jiri Uhlir
 */
@Service("studentService")
public class StudentServiceImpl implements StudentService {

    @Resource(name = "lectureDAO")
    private LectureDAO lectureDao;
    @Resource(name = "studentDAO")
    private StudentDAO studentDao;
    @Autowired
    private Mapper mapper;

    public Mapper getMapper() {
        return mapper;
    }

    public void setMapper(Mapper mapper) {
        this.mapper = mapper;
    }

    public LectureDAO getLectureDao() {
        return lectureDao;
    }

    public void setLectureDao(LectureDAO lectureDao) {
        this.lectureDao = lectureDao;
    }

    public StudentDAO getStudentDao() {
        return studentDao;
    }

    public void setStudentDao(StudentDAO studentDao) {
        this.studentDao = studentDao;
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public StudentDTO add(@Valid StudentDTO student) throws ServiceFailureException {
        if (student == null) {
            throw new IllegalArgumentException("student is null in StudentServiceImpl.add ");
        }

        Student studentToAdd = mapper.map(student, Student.class);

        if (!studentToAdd.getLectures().isEmpty()) {
            throw new IllegalArgumentException("Cannot add student with predefined lectures.");
        }

        studentDao.add(studentToAdd);
        return mapper.map(studentToAdd, StudentDTO.class);

    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void remove(@Valid StudentDTO student) throws ServiceFailureException {
        if (student == null) {
            throw new IllegalArgumentException("student is null in  StudentServiceImpl.remove ");
        }

        if (student.getId() == null) {
            throw new IllegalArgumentException("student.Id is null in StudentServiceImpl.remove ");
        }
        Student toRemove = mapper.map(student, Student.class);

        studentDao.remove(toRemove);
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public StudentDTO modify(@Valid StudentDTO student) throws ServiceFailureException {
        if (student == null) {
            throw new IllegalArgumentException("student is null in  StudentServiceImpl.modify ");
        }
        if (student.getId() == null) {
            throw new IllegalArgumentException("student.Id is null in StudentServiceImpl.modify ");
        }
        Student toModify = mapper.map(student, Student.class);

        studentDao.modify(toModify);

        return mapper.map(toModify, StudentDTO.class);
    }

    @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')")
    @Transactional(readOnly = true)
    public StudentDTO get(Long id) throws ServiceFailureException {
        if (id == null) {
            throw new IllegalArgumentException("ID is null.");
        }

        Student student = studentDao.get(id);
        StudentDTO studentDTO = null;
        if (student != null) {
            studentDTO = mapper.map(student, StudentDTO.class);
        }
        return studentDTO;

    }

    @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')")
    @Transactional(readOnly = true)
    public List<StudentDTO> getAll() throws ServiceFailureException{
        List<Student> students = studentDao.getAll();
        List<StudentDTO> result = new ArrayList<StudentDTO>();
        for (Student student : students) {
            StudentDTO tempStudent = mapper.map(student, StudentDTO.class);
            result.add(tempStudent);
        }

        return result;
    }

    @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public LectureDTO enrollStudentToLecture(@Valid LectureDTO lecture, @Valid StudentDTO student) throws ServiceFailureException {
        if (lecture == null || lecture.getId() == null) {
            throw new IllegalArgumentException("lecture is null in StudentServiceImpl.enrollStudentToLecture.");
        }

        if (student == null || student.getId() == null) {
            throw new IllegalArgumentException("student is null in StudentServiceImpl.enrollStudentToLecture.");
        }

        Student toEnrollStudent = studentDao.get(student.getId());
        Lecture toEnrollLecture = lectureDao.get(lecture.getId());


        studentDao.enrollStudentToLecture(toEnrollLecture, toEnrollStudent);

        return mapper.map(lecture, LectureDTO.class);


    }

    @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')")
    @Transactional(readOnly = true)
    public List<StudentDTO> findByLecture(@Valid LectureDTO lecture) throws ServiceFailureException {
        if (lecture == null) {
            throw new IllegalArgumentException("lecture is null in StudentServiceImpl.findByLecture.");
        }

        Lecture toFind = mapper.map(lecture, Lecture.class);

        List<Student> students = studentDao.findByLecture(toFind);
        List<StudentDTO> result = new ArrayList<StudentDTO>();
        for (Student student : students) {
            StudentDTO tempStudent = mapper.map(student, StudentDTO.class);
            result.add(tempStudent);
        }

        return result;
    }

    @PreAuthorize("hasAnyRole('ROLE_ADMIN','ROLE_USER')")
    @Transactional(readOnly = true)
    public List<StudentDTO> findByName(String name) throws ServiceFailureException {
        if (name == null) {
            throw new IllegalArgumentException("name is null in StudentServiceImpl.findByName.");
        }


        List<Student> students = studentDao.findByName(name);
        List<StudentDTO> result = new ArrayList<StudentDTO>();
        for (Student student : students) {
            StudentDTO tempStudent = mapper.map(student, StudentDTO.class);
            result.add(tempStudent);
        }

        return result;
    }
    
    @Transactional(readOnly=true)
    public StudentDTO getByLogin(String login) throws ServiceFailureException {
        if (login == null) {
            throw new IllegalArgumentException("name is null in StudentServiceImpl.getByLogin.");
        }

        Student student = studentDao.getByLogin(login);
        StudentDTO result = mapper.map(student, StudentDTO.class);

        return result;
    }
}
